package com.tracelog.core.filter;

import org.slf4j.MDC;
import org.springframework.web.filter.OncePerRequestFilter;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.UUID;

/**
 * 日志跟踪过滤器
 * <p>为每个请求添加唯一的跟踪ID</p>
 *
 * @author tracelog
 * @since 1.0.0
 */
public class TraceMdcFilter extends OncePerRequestFilter {

    /**
     * 跟踪ID的键名
     */
    public static final String TRACE_ID_KEY = "traceId";
    
    /**
     * 用户ID的键名
     */
    public static final String USER_ID_KEY = "userId";
    
    /**
     * 请求路径的键名
     */
    public static final String REQUEST_URI_KEY = "requestUri";

    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
        throws ServletException, IOException {
        try {
            // 生成唯一的跟踪ID
            String traceId = generateTraceId(request);
            MDC.put(TRACE_ID_KEY, traceId);
            
            // 将跟踪ID添加到响应头，方便客户端排查问题
            response.addHeader("X-Trace-Id", traceId);
            
            // 记录请求路径
            MDC.put(REQUEST_URI_KEY, request.getRequestURI());
            
            // 记录用户ID（如果有）
            String userId = getUserId(request);
            if (userId != null) {
                MDC.put(USER_ID_KEY, userId);
            }
            
            // 继续过滤链
            filterChain.doFilter(request, response);
        } finally {
            // 清理MDC上下文，防止内存泄漏
            MDC.remove(TRACE_ID_KEY);
            MDC.remove(USER_ID_KEY);
            MDC.remove(REQUEST_URI_KEY);
            MDC.clear();
        }
    }
    
    /**
     * 生成唯一的跟踪ID
     * <p>优先从请求头中获取</p>
     *
     * @param request HTTP请求
     * @return 跟踪ID
     */
    private String generateTraceId(HttpServletRequest request) {
        // 优先从请求头获取，支持分布式追踪
        String traceId = request.getHeader("X-Trace-Id");
        if (traceId == null || traceId.isEmpty()) {
            // 生成新的跟踪ID
            traceId = UUID.randomUUID().toString().replace("-", "");
        }
        return traceId;
    }
    
    /**
     * 获取用户ID（实现可根据实际项目定制）
     *
     * @param request HTTP请求
     * @return 用户ID，未登录返回null
     */
    private String getUserId(HttpServletRequest request) {
        // 示例：从请求头获取用户ID
        return request.getHeader("X-User-Id");
        
        // 实际项目中，可以从Session、Token等获取
        // 例如：从Spring Security获取
        // Authentication auth = SecurityContextHolder.getContext().getAuthentication();
        // if (auth != null && auth.getPrincipal() instanceof UserDetails) {
        //     return ((UserDetails) auth.getPrincipal()).getUsername();
        // }
        // return null;
    }
} 